﻿using System;
using System.Security.Cryptography;

namespace GMS.Utils
{
    public static class GuidHelper
    {
        private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create();

        public static Guid NewSeqGuid()
        {
            return GuidHelper.Create(GuidHelper.SequentialGuidType.SequentialAtEnd);
        }

        private static Guid Create(GuidHelper.SequentialGuidType guidType)
        {
            byte[] data = new byte[10];
            GuidHelper.Rng.GetBytes(data);
            byte[] bytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks / 10000L);
            if (BitConverter.IsLittleEndian)
                Array.Reverse((Array)bytes);
            byte[] b = new byte[16];
            switch (guidType)
            {
                case GuidHelper.SequentialGuidType.SequentialAsString:
                case GuidHelper.SequentialGuidType.SequentialAsBinary:
                    Buffer.BlockCopy((Array)bytes, 2, (Array)b, 0, 6);
                    Buffer.BlockCopy((Array)data, 0, (Array)b, 6, 10);
                    if (guidType == GuidHelper.SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
                    {
                        Array.Reverse((Array)b, 0, 4);
                        Array.Reverse((Array)b, 4, 2);
                        break;
                    }
                    break;
                case GuidHelper.SequentialGuidType.SequentialAtEnd:
                    Buffer.BlockCopy((Array)data, 0, (Array)b, 0, 10);
                    Buffer.BlockCopy((Array)bytes, 2, (Array)b, 10, 6);
                    break;
            }
            return new Guid(b);
        }

        internal enum SequentialGuidType
        {
            SequentialAsString,
            SequentialAsBinary,
            SequentialAtEnd,
        }
    }
}